package com.cskaoyan.javase.oop3._2inner._5anonymous._0introduction;

import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * 匿名内部类
 * 以前讲的成员内部类,静态内部类,局部内部类,无论定义在哪里,无论语法形式如何
 * 它们的语法都是定义了一个类,定义类完毕后,还需要再次创建对象才能够使用
 * 于是,在内部类当中,就出现了一种特殊的内部类——匿名内部类
 * 它的语法时一步到位，直接创建对象，直接就可以使用。
 * 所以匿名内部类，更准确，更具体的称呼是: 匿名内部类对象,它是对象,不是类
 *
 * 匿名内部类的语法:
 *      // 局部位置
 *      new 类名或者接口名(){
 *          // 某类名或接口名的子类的类体
 *      };
 *      // 局部位置
 * 解释:
 *      1.首先要明确的是,匿名内部类是特殊的局部内部类,它仍然是局部内部类
 *          所以仍然要定义在局部位置
 *
 *      2.匿名内部类的语法中存在"new"关键字,它的作用是创建对象
 *      3.(重点)new关键字后面跟的是"类名或者接口名",注意其中类名包括普通类,也包括抽象类
 *          这样的语法形式当然不是说明创建了接口/抽象类的对象
 *          而是因为:
 *          匿名内部类的语法中,隐含了"继承/实现"
 *          new关键字,更具体的来说,表示创建后面"类名/接口名"的子类对象
 *      4.匿名内部类,谁匿名了?
 *          new关键字后面的"类名/接口名"的子类是匿名的
 *          到底创建了什么类型的对象,是不知道的,这个子类是匿名的
 *      5.(重点)语法结构中的"{}"是什么东西??
 *          是这个匿名子类的类体,切记它不是方法体
 *          既然它是类体,所以这个匿名子类当中,是可以自己定义属于这个匿名子类的成员的.
 *
 *      6.在这个语法中:
 *      类名或者接口名(){
 *          // 某类名或接口名的子类的类体
 *      };
 *      这一块属于匿名子类的类体
 *
 * 匿名内部类对象如何使用呢?
 * 有两种方式:
 *      1.用引用接收,用父类引用接收(就是语法结构中的类名/接口名)
 *          优点: 用引用接收,可以多次使用这个匿名子类对象
 *          缺点:
 *              稍微麻烦一点
 *              并且是无法访问子类独有成员的
 *              而且是真的访问不到,因为没有办法强转
 *
 *      2.直接使用,当成一个匿名对象去使用
 *          优点:
 *              稍微方便一些
 *              可以使用子类独有成员
 *          缺点:
 *              一次性的,后面再想用,就用不到了
 *
 * 综上，两种使用方式场景不同。
 * 如果有多次使用需求，就需要父引用接收；
 * 反之如果仅用一次，或者需要访问子类独有成员，就必须直接使用，不能用引用接收。
 *
 * @since 14:37
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 用匿名内部类创建类A的子类对象
        /*
            这是一个没有引用指向的匿名的A类子类对象
            类似于之前讲的匿名对象
          */
        A a = new A() {
            public void test2() {
                System.out.println("匿名子类独有方法!");
            }

            @Override
            void test() {
                System.out.println("我是匿名内部类,重写了普通类A的test方法!");
            }
        };
        a.test();
        // a.test2();
        new A() {
            public void test2() {
                System.out.println("匿名子类独有方法!");
            }

            @Override
            void test() {
                System.out.println("77777777777");
            }
        }.test2();
    }
}

class A {
    void test() {
        System.out.println("普通类A");
    }
}
